package com.cata.mall.security.component;

import cn.hutool.core.util.URLUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * @作者: Tao
 * @日期: 2025/10/11
 * @时间: 10:58
 * @描述: 动态权限数据源，用于获取动态权限规则<pre>
 */
public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private static Map<String, ConfigAttribute> configAttributeMap = null;

    @Autowired
    private DynamicSecurityService dynamicSecurityService;

    /**
     * 初始化数据源加载方法<pre>
     *
     * 该方法使用@PostConstruct注解，确保在Bean初始化完成后自动执行。
     * 通过调用dynamicSecurityService的loadDataSource方法加载安全配置数据，
     * 并将结果存储到configAttributeMap中，用于后续的安全权限验证。
     *
     */
    @PostConstruct
    public void loadDataSource() {
        configAttributeMap = dynamicSecurityService.loadDataSource();
    }

    /**
     * 清除数据源配置信息<pre>
     *
     * 该方法用于清理当前对象中的数据源配置属性映射表，
     * 包括清空映射表中的所有数据并将其引用置为null。
     */
    public void clearDataSource() {
        // 清空配置属性映射表中的所有数据
        configAttributeMap.clear();
        // 将配置属性映射表引用置为null
        configAttributeMap = null;
    }



    /**
     * 获取访问指定对象所需的安全配置属性
     *
     * @param object 表示安全拦截的对象，通常是一个FilterInvocation实例
     * @return 访问该对象所需的配置属性集合
     * @throws IllegalArgumentException 当传入的object参数不合法时抛出此异常
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        if (configAttributeMap == null) this.loadDataSource();
        List<ConfigAttribute>  configAttributes = new ArrayList<>();
        //获取当前访问的路径
        String url = ((FilterInvocation) object).getRequestUrl();
        String path = URLUtil.getPath(url);
        PathMatcher pathMatcher = new AntPathMatcher();
        //获取访问该路径所需资源
        for (String pattern : configAttributeMap.keySet()) {
            if (pathMatcher.match(pattern, path)) {
                configAttributes.add(configAttributeMap.get(pattern));
            }
        }
        // 未设置操作请求权限，返回空集合
        return configAttributes;
    }


    /**
     * 获取所有配置属性
     *
     * @return 配置属性集合，当前实现返回null
     */
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    /**
     * 判断是否支持指定的类
     *
     * @param clazz 要检查的类
     * @return true表示支持，false表示不支持
     */
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

}
